//////////////////////////////////////////////////////////////////////////
// PeekPocket - the hassle-free WiFi scanner for Windows Mobile
// coded by dzolee
// http://dzolee.blogspot.com
//
// WifiPeek: provides access to WiFi information using NDISUIO
// (some code from Daniel Strigl and Pier Paolo Peri)
//////////////////////////////////////////////////////////////////////////

//some people wanted to use this on desktop Windows.
#ifndef _WIN32_WCE
	#error "This code is for WinCE/PocketPC only. It is not compatible with desktop PCs!"
#endif


#include <Windows.h>
#include <winioctl.h>
#include <NtDDNdis.h>
#include <nuiouser.h>

#if _MSC_VER > 1000
#pragma once
#endif

//basid BSSID info struct
struct BSSIDInfo
{
	BYTE BSSID[6];	//mac
	WCHAR SSID[32];
	int RSSI;
	int Channel;
	int Infastructure;
	int Auth;
};

//////////////////////////////////////////////////////////////////////////
//no idea where they might come from
#ifndef SSID_MAX_WPA_IE_LEN
	#define SSID_MAX_WPA_IE_LEN	40
#endif

#ifndef GENERIC_INFO_ELEM
	#define GENERIC_INFO_ELEM	0xdd
#endif

#ifndef RSN_INFO_ELEM
	#define RSN_INFO_ELEM		0x30
#endif

static const BYTE WPA_OUI_TYPE[] = {0x00, 0x50, 0xf2, 0x01};

//////////////////////////////////////////////////////////////////////////
//these modes are not defined in WM SDK, but are present for Win2k/XP
//I rather define a new enum set so there's no need to change the default ntddndis.h header file
//(this enum is backwards-compatible with the one in the SDK, so they can co-exist
typedef enum _NDIS_802_11_AUTHENTICATION_MODE_XP
{
	Ndis802_11AuthModeOpen_XP,
	Ndis802_11AuthModeShared_XP,
	Ndis802_11AuthModeAutoSwitch_XP,
	Ndis802_11AuthModeWPA_XP,
	Ndis802_11AuthModeWPAPSK_XP,
	Ndis802_11AuthModeWPANone_XP,
	Ndis802_11AuthModeWPA2_XP,
	Ndis802_11AuthModeWPA2PSK_XP,
	Ndis802_11AuthModeWPA2None_XP,
	Ndis802_11AuthModeMax_XP               // Not a real mode, defined as upper bound
} NDIS_802_11_AUTHENTICATION_MODE_XP, *PNDIS_802_11_AUTHENTICATION_MODE_XP;

//////////////////////////////////////////////////////////////////////////
class CWifiPeek
{
public:
	CWifiPeek();
	~CWifiPeek();

	bool GetAdapters(LPWSTR pDest, DWORD &dwBufSizeBytes);
	bool RefreshBSSIDs(LPWSTR pAdapter);
	bool GetBSSIDs(LPWSTR pAdapter, struct BSSIDInfo *pDest, DWORD &dwBufSizeBytes, DWORD &dwReturnedItems);	
	bool GetPreferredMACAddress(LPWSTR pAdapter, BYTE *pCurrentMac);

	bool ConnectToAPName(LPWSTR pAdapter, LPWSTR pAPName);
	bool ConnectToMACAddress(LPWSTR pAdapter, BYTE *pMac);
	bool Disconnect(LPWSTR pAdapter);
	bool PrepareToConnect(LPWSTR pAdapter, int iInfrastructureType);

	bool RenewIpAddress(LPWSTR pAdapter);
	bool ReleaseIpAddress(LPWSTR pAdapter);

private:
	bool OpenDriver();
	void CloseDriver();
	bool IsWireless(LPWSTR pAdapter);

	bool SetInfrastructureMode(LPWSTR pAdapter,  int iInfrastructureType);
	bool SetPrivacyFilter(LPWSTR pAdapter);
	bool SetAuthenticationMode(LPWSTR pAdapter);
	bool SetEncryptionStatus(LPWSTR pAdapter);

	int GetAuthModeFromIEs(BYTE *ie, size_t ie_len);

	CRITICAL_SECTION m_Lock;
	HANDLE m_hNDUIO;
};

